#include <qapplication.h>
#include "window.moc"
#include "glwidget.h"
#include "ucdinputfile.h"

#include "visFlowTopology.h"

using namespace visualization;
using namespace std;

Model t;
intgResults *forward, *backward;
// This is used to display the saddle point on the screen.
vector<saddlePoint> saddle;
size_t n;
Point *fs, *bs;
double xmin, xmax, ymin, ymax, zmin, zmax;
double c[3]; 

class glW: public GLWidget
{
public:
	glW(QWidget *parent = 0) 
	     : GLWidget(parent)
	{}

public:
	GLuint makeObject();
};

class win : public Window
{
public:
	win(glW *glwidget)
		: Window(glwidget)
	{}
};

void compute(string filename);
int main(int argc, char *argv[])
{
	if(argc < 2)
	{
		cerr << "Input a data file please..." << endl;
		return 0;
	}
	compute(argv[1]);
  QApplication app(argc, argv);
	glW *glw = new glW();
	glw->setFileName(argv[1]);
  win window(glw);
	window.generateWindow();
  window.show();
  app.exec();
	return 0;
}

void compute(string filename)
{
	UCDInputFile file(filename);
	file.FGetModel(t);	
	t.buildKDTree();

	visFlowTopology ft(&t);
	ft.setRdAndSmpRate(1, 4);
	ft.setZero(1e-6);
	ft.setDelt(1e-3);
	ft.setDiavationFromSaddle(1);
	ft.setNeighbourNum(10);
	ft.setDisError(4);
	ft.determineCriticalPoint();
	ft.preProcessSaddles();
	ft.integrateCurves(forward, backward);
	
	saddle = ft.getSaddles(n);
	ft.getSources(fs, bs);
	t.getBound(xmin, xmax, ymin, ymax, zmin, zmax);
	c[0] = (xmin+xmax)/2;
	c[1] = (ymin+ymax)/2;
	c[2] = (zmin+zmax)/2;

}

GLuint glW::makeObject()
{
	GLuint list = glGenLists(1);
	glNewList(list, GL_COMPILE);

	double scale = 100;
	glBegin(GL_LINES);
	drawFramework(xmin-c[0], xmax-c[0], ymin-c[1], ymax-c[1], zmin-c[2], zmax-c[2], scale);
	glEnd();

	glPointSize(5);
	glColor3f(0.0, 0.0, 0.0);
	glBegin(GL_POINTS);		
		for(size_t i = 0; i < saddle.size(); i++)
		{
			glVertex3f( (saddle[i].x-c[0])/scale, (saddle[i].y-c[1])/scale, 0);
		}
	glEnd();

	for(size_t i = 0; i < forward->size(); i++)
	{
		glBegin(GL_LINE_STRIP);		
			for(size_t j = 0; j < (*forward)[i].size(); j++)
				glVertex3f(((*forward)[i][j].getX()-c[0])/scale, ((*forward)[i][j].getY()-c[1])/scale, 0);
		glEnd();
	}
	for(size_t i = 0; i < backward->size(); i++)
	{
		glBegin(GL_LINE_STRIP);		
			for(size_t j = 0; j < (*backward)[i].size(); j++)
				glVertex3f(((*backward)[i][j].getX()-c[0])/scale, ((*backward)[i][j].getY()-c[1])/scale, 0);
		glEnd();
	}

	for(size_t i = 0; i < n; i++)
	{
		glBegin(GL_LINE_STRIP);
			for(size_t j = 0; j < 2; j++)	
			{	
				glVertex3f((fs[2*i+j].getX()-c[0])/scale, (fs[2*i+j].getY()-c[1])/scale, 0);
			}
		glEnd();	
		glBegin(GL_LINE_STRIP);
			for(size_t j = 0; j < 2; j++) 
			{	
				glVertex3f((bs[2*i+j].getX()-c[0])/scale, (bs[2*i+j].getY()-c[1])/scale, 0);
			}
		glEnd();
	}
	delete []fs;
	delete []bs;

	glEndList();
	return list;
}

